﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CallMVC.Models;
using DBManager;
using System.Text;
using System.Web.Security;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.Threading;

namespace CallMVC.Controllers
{
    public class HomeController : Controller
    {
        Mutex mutex = new Mutex(false);
        
        Random r;
        public HomeController()
        {
            r = new Random();
            
        }

        private string RandomString(int size, bool lowerCase)
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }
            if (lowerCase)
                return builder.ToString().ToLower();
            return builder.ToString();
        }

        public ActionResult Index()
        {
            LoginModel model = new LoginModel();
            ViewBag.Customers = GetCustomers();

            if (User.Identity.IsAuthenticated)
            {
                List<Access> accList = DBManager.DBManager.Instance.GetAcesss(User.Identity.Name);
                List<Calculation> calList = new List<DBManager.Calculation>();
                Dictionary<int, Calculation> set = new Dictionary<int, Calculation>();

                foreach (Access item in accList)
                {

                    if (item.FirstTimePaid == true || (item.ExpiryDate == null || item.ExpiryDate != null &&
                     item.ExpiryDate.Value >= DateTime.Today))
                    {

                        Calculation calc = DBManager.DBManager.Instance.GetCalculation(item.CalculationID);

                        if (calc != null)
                        {
                            calList.Add(calc);
                            set.Add(calc.ID, calc);
                        }

                    }
                }

                ViewBag.Calculations = calList;
            }
            return View(model);
        }

        private List<Customer> GetCustomers()
        {
            return DBManager.DBManager.Instance.GetCustomerList();
        }
 

        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }

        public ActionResult TestCalcOut()
        {
            ViewBag.Message = "Your contact page.";
            return View();
        }

        public ActionResult CalcOut(string calculationId)
        {
            try
            {
                DBManager.DBManager.Instance.mutexlock();
                Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);
                LoginModel model = new LoginModel();

                if (Session["orderId"] != null)
                {
                    OrderControl orderControl = DBManager.DBManager.Instance.GetOrderControl(Session["orderId"].ToString());
                    ViewBag.OrderId = orderControl.OrderID;
                    ViewBag.OrderStatus = orderControl.OrderStatus;
                }
                ViewBag.Calculation = calculation;
                ViewBag.Customer = calculation.Customer;

                DBManager.DBManager.Instance.mutexUnlock();


                return View(model);

            }
            catch (Exception)
            {
                DBManager.DBManager.Instance.mutexUnlock();
                throw; 
            }

        }


        public ActionResult InfoPage(string customerId)
        {
            Customer customer = DBManager.DBManager.Instance.GetCustomer(customerId);
            Customer custStd = DBManager.DBManager.Instance.GetCustomer("Standard");
            LoginModel model = new LoginModel();

            ViewBag.Customer = customer;

            //Session.Remove("orderId");

            //if (User.Identity.IsAuthenticated)
            //{
            //   DBManager.User user = DBManager.DBManager.Instance.GetUser(User.Identity.Name);

            //    ViewBag.Calculations = user.CalculationList(customer);

            //    return View(model);

            //}

            //ViewBag.Calculations = customer.CalculationList;
            ViewBag.Customer = customer;
            ViewBag.CustStd = custStd;

            return View(model);
        }

        public ActionResult Calculation(string customerId)
        {
            Customer customer = DBManager.DBManager.Instance.GetCustomer(customerId);
            LoginModel model = new LoginModel();

            ViewBag.Customer = customer;

            Session.Remove("orderId");

            if (User.Identity.IsAuthenticated)
            {
                DBManager.User user = DBManager.DBManager.Instance.GetUser(User.Identity.Name);

                ViewBag.Calculations = user.CalculationList(customer);
               
                return View(model);
                
            }

            ViewBag.Calculations = customer.CalculationList;
            
            return View(model);
        }

        public ActionResult SavedCalc(string calculationId)
        {
            string userId = User.Identity.Name;
            Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);

            List<OrderControl> orders = DBManager.DBManager.Instance.GetOrderControlList(calculationId, userId);
            OrderControl latestOrder = DBManager.DBManager.Instance.GetLatestOrderControl(calculationId, userId);
            Session.Remove("orderId");

            if (orders.Count == 0 && latestOrder == null)
            {
                return RedirectToAction("CalcInput", new { calculationId = calculationId });
            }

            LoginModel model = new LoginModel();
            ViewBag.Calculation = calculation;
            ViewBag.Orders = orders;
            ViewBag.LatestOrder = latestOrder;
            ViewBag.Customer = calculation.Customer;
            return View(model);
        }

        public ActionResult CalcInput(string calculationId, string orderId = "")
        {

            try
            {
                DBManager.DBManager.Instance.mutexlock();

                DBManager.DBManager.Instance.refreshInputGroupS();

                Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);

                if (!User.Identity.IsAuthenticated)
                {
                    if (calculation.isFreeCalculation == false)
                    {
                        DBManager.DBManager.Instance.mutexUnlock();
                        return RedirectPermanent("/CalcApp/Account/Login");

                    }

                }

                LoginModel model = new LoginModel();
                ViewBag.Calculation = calculation;
                ViewBag.isLoadOrder = false;
                ViewBag.Customer = calculation.Customer;
                if (orderId != "")
                {
                    if (Session["orderId"] != null)
                    {
                        OrderControl orderControl = DBManager.DBManager.Instance.GetOrderControl(Session["orderId"].ToString());
                        ViewBag.isLoadOrder = true;
                        ViewBag.OrderControl = orderControl;
                    }
                    else
                    {
                        OrderControl orderControl = DBManager.DBManager.Instance.GetOrderControl(orderId.ToString());
                        ViewBag.isLoadOrder = true;
                        ViewBag.OrderControl = orderControl;
                    }
                }
                else if (Session["orderId"] != null)
                {
                    OrderControl orderControl = DBManager.DBManager.Instance.GetOrderControl(Session["orderId"].ToString());
                    ViewBag.isLoadOrder = true;
                    ViewBag.OrderControl = orderControl;
                }



                DBManager.DBManager.Instance.mutexUnlock();
                return View(model);

            }
            catch (Exception)
            {
                DBManager.DBManager.Instance.mutexUnlock();
                throw;
            }
        }

        public ActionResult SaveOrderCtrl(string calculationId)
        {
            string userId = User.Identity.Name;

            Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);
            List<OrderControl> orders = DBManager.DBManager.Instance.GetOrderControlList(calculationId, userId);
            Session.Remove("orderId");

            LoginModel model = new LoginModel();
            ViewBag.Orders = orders;
            ViewBag.Calculation = calculation;
            ViewBag.Customer = calculation.Customer;

            return View(model);
           
        }

        [HttpPost]
        public ActionResult View1(string calculationId, FormCollection formCollection)
        {
            return View();
        }

        public ActionResult View1(string calculationId)
        {
            return View();
        }

        public Boolean GenerateGraph(Calculation calculation, String orderId)
        {

            string picturePath = Server.MapPath("~/Graph/");
            string pictureName = RandomString(5,false) +".jpg";
            //string pictureName = "graph.jpg";
           // ViewBag.pictureName = pictureName;
            if (System.IO.File.Exists(picturePath))
            System.IO.File.Delete(picturePath);

            ChartDesign chartDesign = DBManager.DBManager.Instance.GetChartDesign(calculation.CalculationID);

            if (chartDesign!=null)
            {
                using (Chart ch = new Chart())
                {
                    ch.ChartAreas.Add(new ChartArea());
                    ch.ChartAreas["ChartArea1"].AxisX.Title = "År";
                    //ch.ChartAreas["ChartArea1"].AxisY.Title = "Beløb";
                    ch.ChartAreas["ChartArea1"].AxisY.LabelStyle.Format = "##,#";
                    ch.ChartAreas["ChartArea1"].AxisX.LabelStyle.IsEndLabelVisible = false;
                    ch.ChartAreas["ChartArea1"].AxisY.LabelStyle.IsEndLabelVisible = false;
                    
                    ch.Legends.Add("Legend");
                    ch.Legends["Legend"].Docking = Docking.Bottom;

                    //get value serie1
                    //chartDesign.ValueSerie1;
                    List<ChartOutput> chartOutputs1 = DBManager.DBManager.Instance.GetChartOutputList(calculation.CalculationID, chartDesign.ValueSerie1, orderId);
                    //get value serie2
                    //chartDesign.ValueSerie2;
                    List<ChartOutput> chartOutputs2 = DBManager.DBManager.Instance.GetChartOutputList(calculation.CalculationID, chartDesign.ValueSerie2, orderId);                    
                    //get value serie3
                    //chartDesign.ValueSerie3;
                    List<ChartOutput> chartOutputs3 = DBManager.DBManager.Instance.GetChartOutputList(calculation.CalculationID, chartDesign.ValueSerie3, orderId);

                    double findMax = 0;
                    double findMin = 0;
                    bool isBelob1000 = false;
                    bool isBelob1000000 = false;
                    bool isFirstTime = true;
                    if (chartOutputs1 != null)
                    {                        
                        foreach (ChartOutput chartOutput in chartOutputs1)
                        {                           
                            //DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), chartOutput.valueFormat);

                            if (isFirstTime == true)
                            {
                                findMin = chartOutput.valueFormat;
                                findMax = chartOutput.valueFormat;
                            }
                            if (chartOutput.valueFormat > findMax)
                            {
                                findMax = chartOutput.valueFormat;
                            }
                            if (chartOutput.valueFormat < findMin)
                            {
                                findMin = chartOutput.valueFormat;
                            }
                        }
                    }

                    if (chartOutputs2 != null)
                    {
                        foreach (ChartOutput chartOutput in chartOutputs2)
                        {
                            //DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), chartOutput.valueFormat);
                            if (chartOutput.valueFormat > findMax)
                            {
                                findMax = chartOutput.valueFormat;
                            }
                            if (chartOutput.valueFormat < findMin)
                            {
                                findMin = chartOutput.valueFormat;
                            }                
                        }
                    }

                    if (chartOutputs3 != null)
                    {
                        foreach (ChartOutput chartOutput in chartOutputs3)
                        {
                            //DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), chartOutput.valueFormat);
                            if (chartOutput.valueFormat > findMax)
                            {
                                findMax = chartOutput.valueFormat;
                            }
                            if (chartOutput.valueFormat < findMin)
                            {
                                findMin = chartOutput.valueFormat;
                            }
                        }
                    }

                    if (( Math.Abs(findMax)/ 1000000 >= 100) || ( Math.Abs(findMin)/ 1000000 >= 100))
                    {
                        //show ‘1.000.000 Beløb’
                        ch.ChartAreas["ChartArea1"].AxisY.Title = "1.000.000 " + chartDesign.YAxis;
                        isBelob1000000 = true;
                    }

                    else if ((Math.Abs(findMax) / 1000 >= 100) || (Math.Abs(findMin) / 1000 >= 100))
                    {
                        //show ‘1.000 Beløb’
                        ch.ChartAreas["ChartArea1"].AxisY.Title = "1.000 " + chartDesign.YAxis;
                        isBelob1000 = true;
                    }
                    else
                    {
                        ch.ChartAreas["ChartArea1"].AxisY.Title = chartDesign.YAxis;
                    }

                    ch.ChartAreas["ChartArea1"].AxisX.Title = chartDesign.XAxis;


                    if (chartOutputs1 != null)
                    {
                        List<DataPoint> series1 = new List<DataPoint>();
                        foreach (ChartOutput chartOutput in chartOutputs1)
                        {
                            char[] spr = { '$' };
                            string[] strs = chartOutput.OutputValue.Split(spr);

                            double yValue;
                            if (isBelob1000000)
                            {
                                yValue = chartOutput.valueFormat/1000000;
                            }
                            else if (isBelob1000)
                            {
                                yValue = chartOutput.valueFormat/1000;
                            }
                            else
                            {
                                yValue = chartOutput.valueFormat;
                            }

                            try
                            {
                                DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), yValue);
                                series1.Add(data);

                            }
                            catch (Exception)
                            {
                                
                                ;
                            }

                        }
                        Series s1 = new Series();
                        s1.LegendText = chartDesign.DescSerie1;
                        s1.ChartType = SeriesChartType.Column;
                        foreach (var pnt in series1) s1.Points.Add(pnt);
                        //s1.IsValueShownAsLabel = true;
                        //s1.Label = "#VALY{$#.###}";
                        if(s1.Points.Count > 0)
                            ch.Series.Add(s1);
                    }

                    if (chartOutputs2 != null)
                    {
                        List<DataPoint> series2 = new List<DataPoint>();
                        foreach (ChartOutput chartOutput in chartOutputs2)
                        {
                            char[] spr = { '$' };
                            string[] strs = chartOutput.OutputValue.Split(spr);

                            double yValue;
                            if (isBelob1000000)
                            {
                                yValue = chartOutput.valueFormat / 1000000;
                            }
                            else if (isBelob1000)
                            {
                                yValue = chartOutput.valueFormat / 1000;
                            }
                            else
                            {
                                yValue = chartOutput.valueFormat;
                            }

                            try
                            {
                                DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), yValue);
                                series2.Add(data);
                            }
                            catch (Exception)
                            {
                                
                                ;
                            }

                        }
                        Series s2 = new Series();
                        s2.LegendText = chartDesign.DescSerie2;
                        s2.ChartType = SeriesChartType.Column;
                        foreach (var pnt in series2) s2.Points.Add(pnt);
                        //s2.IsValueShownAsLabel = true;
                        //s2.Label = "#VALY{$#.###}";
                        if(s2.Points.Count > 0)
                            ch.Series.Add(s2);
                    }

                    if (chartOutputs3 != null)
                    {
                        List<DataPoint> series3 = new List<DataPoint>();
                        foreach (ChartOutput chartOutput in chartOutputs3)
                        {
                            char[] spr = {'$'};
                            string[] strs = chartOutput.OutputValue.Split(spr);

                            double yValue;
                            if (isBelob1000000)
                            {
                                yValue = chartOutput.valueFormat / 1000000;
                            }
                            else if (isBelob1000)
                            {
                                yValue = chartOutput.valueFormat / 1000;
                            }
                            else
                            {
                                yValue = chartOutput.valueFormat;
                            }

                            try
                            {
                                DataPoint data = new DataPoint(Convert.ToDouble(chartOutput.XAxisValue), yValue);
                                series3.Add(data);
                            }
                            catch (Exception)
                            {
                                
                                ;
                            }

                        }

                        Series s3 = new Series();
                        s3.LegendText = chartDesign.DescSerie3;
                        s3.ChartType = SeriesChartType.Column;
                        foreach (var pnt in series3) s3.Points.Add(pnt);
                        //s3.IsValueShownAsLabel = true;
                        //s3.Label = "#VALY{$#.###}"; 
                       

                        if(s3.Points.Count > 0)
                            ch.Series.Add(s3);
                    }
                    //ch.Series[0].LabelFormat = "#,###";
                    //ch.Series[1].LabelFormat = "#,###";
                    //ch.Series[2].LabelFormat = "#,###";

                   if(!System.IO.Directory.Exists(picturePath))
                       System.IO.Directory.CreateDirectory(picturePath);
                  
                    ch.SaveImage(picturePath + pictureName, System.Drawing.Imaging.ImageFormat.Png);

                    ViewBag.pictureName = pictureName;
                }
                return true;
            }
            return false;
        }

        [HttpPost]
        public ActionResult ChartNOut(string calculationId, FormCollection formCollection)
        {
            OrderControl orderControl = new OrderControl();
            Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);
            ViewBag.Calculation = calculation;
            return View();
        }

        public ActionResult ChartNOut(string calculationId)
        {
            return View();
        }

        [HttpPost]
        public ActionResult CalcOut(string calculationId,FormCollection formCollection)
        {
            try
            {

                DBManager.DBManager.Instance.mutexlock();
                OrderControl orderControl = new OrderControl();
                Calculation calculation = DBManager.DBManager.Instance.GetCalculation(calculationId);

                orderControl.CalculationID = calculation.CalculationID;
                string orderId = DateTime.Now.ToString("yyyyMMddHH:mm:ss");
                orderId += RandomString(15, true);
                orderControl.OrderStatus = 0;
                orderControl.OrderID = orderId;

                if (User.Identity.IsAuthenticated)
                {
                    orderControl.UserID = User.Identity.Name;
                }

                DBManager.DBManager.Instance.Add(orderControl);
                DBManager.DBManager.Instance.Save();

                foreach (string _formData in formCollection)
                {
                    if (_formData != "SaveCalc")
                    {

                        InputValue input = new InputValue();
                        input.CalculationID = calculation.CalculationID;
                        input.FieldID = _formData;

                        InputDesign design = DBManager.DBManager.Instance.GetInputDesign(input.FieldID, input.CalculationID);

                        if (design.isPercent || formCollection[_formData].Contains('%'))
                        {
                            string data = formCollection[_formData];

                            data = data.Replace("%", null).Trim();

                            Decimal d = Decimal.Parse(data) / 100M;

                            input.InputValue1 = d.ToString();
                        }
                        else if (design.isNumber)
                        {
                            string s = formCollection[_formData];

                            if (formCollection[_formData] == "")
                            {
                                input.InputValue1 = Decimal.Parse(design.DefaultValue).ToString();
                            }
                            else
                                input.InputValue1 = Decimal.Parse(formCollection[_formData]).ToString();
                        }
                        else if (design.isDateTime)
                        {
                            DateTime date = DateTime.ParseExact(formCollection[_formData], "yyyy-MM-dd", null);

                            string value = date.ToString(design.NumberFormat.Replace("mm", "MM"));
                            input.InputValue1 = value;
                        }

                        else
                        {

                            input.InputValue1 = formCollection[_formData];
                        }

                        input.OrderID = orderId;
                        DBManager.DBManager.Instance.Add(input);
                    }
                    else
                    {
                        if (formCollection[_formData] == "true,false")
                        {
                            orderControl.Saved = true;
                        }
                        else
                            orderControl.Saved = false;
                    }
                }

                DBManager.DBManager.Instance.Save();

                orderControl.OrderStatus = 1;

                DBManager.DBManager.Instance.Save();

                int time_wait = 0;

                while (time_wait <= 30000)
                {
                    DBManager.DBManager.Instance.refreshOrderControl(orderControl);

                    if (orderControl.OrderStatus == 2)
                        break;

                    System.Threading.Thread.Sleep(100);

                    time_wait += 100;
                }

                if (orderControl.OrderStatus == 2)
                {
                    LoginModel model = new LoginModel();
                    Session["orderId"] = orderControl.ID;
                    ViewBag.Calculation = calculation;
                    ViewBag.OrderId = orderId;
                    ViewBag.OrderStatus = 2;
                    ViewBag.Customer = calculation.Customer;
                    //return RedirectToRoutePermanent("CalcOut", new { calculationId = calculationId, orderId = orderId,orderStatus = orderControl.OrderStatus });
                    //return RedirectPermanent("Home/CalcOut?calculationId=" + calculationId + "&orderId=" + orderId + "&orderStatus="+orderControl.OrderStatus);


                    List<LineViewModel> lineViewModel = new List<LineViewModel>();

                    LineViewModel l1 = new LineViewModel();
                    l1.LineName = "First line";
                    l1.id = 1;
                    l1.data = new List<LineDataViewModel>();
                    for (int i = 0; i < 10; i++)
                        l1.data.Add(new LineDataViewModel() { Date = DateTime.Now.AddDays(r.Next(1, 25)), Value = r.Next(1, 10) });
                    lineViewModel.Add(l1);

                    LineViewModel l2 = new LineViewModel();
                    l2.LineName = "Second line";
                    l2.id = 2;
                    l2.data = new List<LineDataViewModel>();
                    for (int i = 0; i < 10; i++)
                        l2.data.Add(new LineDataViewModel() { Date = DateTime.Now.AddDays(r.Next(1, 25)), Value = r.Next(1, 10) });
                    lineViewModel.Add(l2);


                    ViewBag.LineViewModel = lineViewModel;

                    if (GenerateGraph(calculation, orderId))
                    {
                        ViewBag.IsGraphExist = true;
                    }
                    else
                    {
                        ViewBag.IsGraphExist = false;
                    }

                    var view = View(model);

                    // view.MasterName = "CalcOut";

                    //return RedirectPermanent("/Home/CalcOut?calculationId="+ calculationId);
                    DBManager.DBManager.Instance.mutexUnlock();
                    return view;
                }
                else
                {
                    orderControl.OrderStatus = 6;
                    DBManager.DBManager.Instance.Save();
                    LoginModel model = new LoginModel();
                    ViewBag.Calculation = calculation;
                    ViewBag.OrderId = orderId;
                    ViewBag.OrderStatus = orderControl.OrderStatus;
                    ViewBag.Customer = calculation.Customer;
                    var view = View(model);

                    // view.MasterName = "CalcOut";
                    DBManager.DBManager.Instance.mutexUnlock();
                    return view;
                }
            }
            catch (Exception)
            {
                DBManager.DBManager.Instance.mutexUnlock();
                throw;
               // return 
            }
         
        }
    }
}
